package cn.tedu.ivos.audit.service.impl;

import cn.tedu.ivos.application.mapper.ApplicationMapper;
import cn.tedu.ivos.application.pojo.entity.Application;
import cn.tedu.ivos.audit.mapper.AuditMapper;
import cn.tedu.ivos.audit.pojo.dto.AuditQuery;
import cn.tedu.ivos.audit.pojo.dto.AuditSaveParam;
import cn.tedu.ivos.audit.pojo.entity.Audit;
import cn.tedu.ivos.audit.pojo.vo.AuditVO;
import cn.tedu.ivos.audit.service.AuditService;
import cn.tedu.ivos.base.enums.ApplicationStatusEnum;
import cn.tedu.ivos.base.enums.AuditStatusEnum;
import cn.tedu.ivos.user.mapper.UserMapper;
import cn.tedu.ivos.user.pojo.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;

/* @Transactional是Spring框架提供的一个用于管理事务的注解,可以管理类或方法上的事务
在对数据库做操作的时候,可以保证该类下的方法对应的数据操作都在同一个事务中
确保原子性,要么都成功,要么都失败 */
@Transactional
@Slf4j
@Service
public class AuditServiceImpl implements AuditService {
	@Autowired
	AuditMapper auditMapper;
	@Autowired
	UserMapper userMapper;
	@Autowired
	ApplicationMapper applicationMapper;
	
	
	@Override
	public void insertAudit(Application application) {
		log.debug("新增审批单业务,参数={}", application);
		//1.获取审批人id集合
		List<Long> userIdList = application.getAuditUserIdList();//[106,103]
		//2.遍历上方的审批人id集合,有几个id,生成几个审批单
		for (int i = 0; i < userIdList.size(); i++) {
			Audit audit = new Audit();
			audit.setApplicationId(application.getId());//设置批哪个申请单
			audit.setAuditUserId(userIdList.get(i));//设置审批人id
			audit.setAuditSort(i);//设置审批排序
			if (i == 0) {
				audit.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
			} else {
				audit.setAuditStatus(AuditStatusEnum.PENDING.getCode());
			}
			audit.setCreateTime(new Date());
			auditMapper.insert(audit);
		}
	}
	
	@Override
	public List<AuditVO> selectAuditByApplicationId(Long id) {
		log.debug("根据申请单id查询对应所有审批单业务,参数={}", id);
		return auditMapper.selectAuditByApplicationId(id);
	}
	
	@Override
	public List<AuditVO> selectAudit(AuditQuery auditQuery) {
		log.debug("查询审批单业务,参数={}", auditQuery);
		List<AuditVO> list = auditMapper.selectAudit(auditQuery);
		for (int i = 0; i < list.size(); i++) {
			AuditVO auditVO = list.get(i);
			assignAuditUserList(auditVO);
		}
		return list;
	}
	
	@Override
	public void updateAudit(AuditSaveParam auditSaveParam) {
		log.debug("审批申请单业务,参数={}", auditSaveParam);
		//更新当前审批人的审批单
		Audit audit = new Audit();
		BeanUtils.copyProperties(auditSaveParam,audit);
		audit.setUpdateTime(new Date());
		auditMapper.update(audit);
		//还得继续更新当前审批单批的这个申请单
		Application application = new Application();
		application.setId(audit.getApplicationId());
		application.setUpdateTime(new Date());
		//因为审批通过与驳回都是更新方法,所以需要判断前端传过来的审批状态(30或40),分别处理
		if(audit.getAuditStatus().equals(AuditStatusEnum.AUDITED.getCode())){//审批通过
			/* 继续查其它审批单:其它审批单与当前审批单,批同一个申请单 */
			AuditQuery auditQuery = new AuditQuery();
			auditQuery.setApplicationId(audit.getApplicationId());
			//查询其它未审批的审批单总数
			Integer count = auditMapper.selectRestAuditCount(auditQuery);
			if(count>0){//还有未审批的审批单
				/* 查下一条未审批的审批单,做更新 20=>10 */
				auditQuery.setAuditSort(audit.getAuditSort()+1);
				List<AuditVO> auditVOList = auditMapper.selectAudit(auditQuery);
				if(auditVOList !=null && auditVOList.size()>0){
					AuditVO auditVO = auditVOList.get(0);
					//创建第2个审批实体类对象,用于第二条审批单更新
					Audit audit2 = new Audit();
					audit2.setId(auditVO.getId());
					audit2.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
					audit2.setUpdateTime(new Date());
					auditMapper.update(audit2);
				}
				//还要设置申请单状态为审核中
				application.setStatus(ApplicationStatusEnum.AUDIT.getCode());
				applicationMapper.update(application);
			}else{//没有未审批的审批单
				application.setStatus(ApplicationStatusEnum.AUDITED.getCode());
				applicationMapper.update(application);
			}
		}else{//审批驳回
			AuditQuery auditQuery = new AuditQuery();
			auditQuery.setApplicationId(audit.getApplicationId());
			//根据申请单id查出批此申请单的所有审批单
			List<AuditVO> auditVOList = auditMapper.selectAudit(auditQuery);
			if(auditVOList != null && auditVOList.size()>0){
				for(int i = 0; i < auditVOList.size(); i++){
					AuditVO auditVO = auditVOList.get(i);
					//如果当前遍历到的这个审批单对象为"待我审核"
					if(auditVO.getAuditStatus().equals(AuditStatusEnum.PENDING.getCode())){
						auditMapper.deleteById(auditVO.getId());
					}
				}
			}
			//设置申请单的状态为驳回,并设置驳回原因,更新即可
			application.setStatus(ApplicationStatusEnum.REJECT.getCode());
			application.setRejectReason(auditSaveParam.getRejectReason());
			applicationMapper.update(application);
		}
	}
	
	private void assignAuditUserList(AuditVO auditVO) {
		List<Long> auditUserIdList = new ArrayList<>();//准备空集合放审批人id
		List<String> auditUsernameList = new ArrayList<>();//准备空集合放审批人姓名
		//根据申请单id查询批此申请单的所有审批单集合
		List<AuditVO> auditVOList =
				auditMapper.selectAuditByApplicationId(auditVO.getApplicationId());
		for (int i = 0; i < auditVOList.size(); i++) {//遍历查出来的审批单集合
			Long userId = auditVOList.get(i).getAuditUserId();//获取当前审批单中的审批人id
			auditUserIdList.add(userId);//将本轮取出的审批人id添加到上方的空集合中
			UserVO userVO = userMapper.selectById(userId);//根据审批人id查询审批人VO
			auditUsernameList.add(userVO.getUsername());//将本轮取出的审批人姓名添加到上方的集合中
		}
		StringJoiner stringJoiner = new StringJoiner(",");//准备拼接工具
		for(String username : auditUsernameList){//循环上方的审批人姓名集合
			stringJoiner.add(username);//将遍历到的审批人姓名添加到拼接工具中
		}
		auditVO.setAuditUsernameList(stringJoiner.toString());//给传入的审批VO设置审批人姓名字符串
		auditVO.setAuditUserIdList(auditUserIdList);//给传入的审批VO设置审批人id集合
	}
}
